package cn.huhaoran.yaoyaolingxian.ui.CustomTreeTableImpl;

import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import git4idea.repo.GitRepository;
import git4idea.repo.GitRepositoryManager;
import org.jdesktop.swingx.JXTreeTable;
import org.jdesktop.swingx.treetable.TreeTableModel;

import javax.swing.event.MouseInputListener;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.text.SimpleDateFormat;
import java.util.*;

public class CreateGitBranchTreeTableUtils {

    public static void initExportTable(Project project, JXTreeTable treeTable,GitBranchNode exportRootNode){
        // 使用工具类初始化 exportTable 组件
        exportRootNode = CreateGitBranchTreeTableUtils.setupGitBranchTreeTable(project, treeTable);
        // 自动展开到当前分支
        CreateGitBranchTreeTableUtils.expandToCurrentBranch(treeTable, exportRootNode);
        // 检查是否有足够的列可以移除
        if (treeTable.getColumnModel().getColumnCount() > 3) {
            treeTable.getColumnModel().removeColumn(treeTable.getColumnModel().getColumn(3));
        }
    }


    /**
     * setupGitBranchTreeTable 通过项目赋值JXTreeTable数据
     *
     * @param project   com.intellij.openapi.project.Project
     * @param treeTable org.jdesktop.swingx.JXTreeTable
     * @return cn.huhaoran.yaoyaolingxian.ui.CustomTreeTableImpl.GitBranchNode
     * @author huhaoran
     * @date 2024/8/12
     */
    public static GitBranchNode setupGitBranchTreeTable(Project project, JXTreeTable treeTable) {
        // 从 Git 仓库生成树结构
        GitBranchNode root = createTreeFromGitRepositories(project);
        return setGitBranchTreeTableNode(root, treeTable);
    }

    public static GitBranchNode setupGitBranchTreeTable(GitBranchNode root, JXTreeTable treeTable) {
        // 从 GitBranchNode 生成表格结构
        return setGitBranchTreeTableNode(root, treeTable);
    }

    private static MouseAdapter existingListener = null; // 用于存储已添加的监听器
    private static GitBranchNode setGitBranchTreeTableNode(GitBranchNode root, JXTreeTable treeTable) {

        // 创建TreeTable模型
        GitBranchTreeTableModel treeTableModel = new GitBranchTreeTableModel(root);

        // 设置TreeTable的模型
        treeTable.setTreeTableModel(treeTableModel);
        treeTable.setRootVisible(false); // 隐藏根节点

        // 应用自定义渲染器
        CustomTreeCellRenderer renderer = new CustomTreeCellRenderer();
        treeTable.setTreeCellRenderer(renderer);
        // 移除现有的自定义双击监听器（如果存在）
        if (existingListener != null) {
            treeTable.removeMouseListener(existingListener);
        }

        // 创建并添加新的自定义双击监听器
        existingListener = new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                if (e.getClickCount() % 2 == 0) { // 检测双击事件
                    int row = treeTable.rowAtPoint(e.getPoint());
                    int column = treeTable.columnAtPoint(e.getPoint());

                    if (column == 0) { // 仅在第一列双击时切换选中状态
                        TreePath path = treeTable.getPathForRow(row);
                        if (path != null) {
                            Object node = path.getLastPathComponent();
                            if (node instanceof GitBranchNode) {
                                GitBranchNode branchNode = (GitBranchNode) node;
                                branchNode.toggleSelected(); // 切换选中状态
                                treeTable.updateUI(); // 强制刷新表格以反映更改
                            }
                        }
                    }
                }
            }
        };
        // 处理鼠标双击事件，切换选中状态
        treeTable.addMouseListener(existingListener); // 添加新的监听器
     /*   treeTable.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                if (e.getClickCount() % 2 == 0) { // 检测双击事件及其倍数
                    int row = treeTable.rowAtPoint(e.getPoint());
                    int column = treeTable.columnAtPoint(e.getPoint());

                    if (column == 0) { // 仅在第一列双击时切换选中状态
                        TreePath path = treeTable.getPathForRow(row);
                        if (path != null) {
                            Object node = path.getLastPathComponent();
                            if (node instanceof GitBranchNode) {
                                GitBranchNode branchNode = (GitBranchNode) node;
                                branchNode.toggleSelected(); // 切换选中状态
                                treeTable.updateUI(); // 强制刷新表格以反映更改
                            }
                        }
                    }
                }
            }
        });*/
        return root; // 返回根节点
    }

    /**
     * expandToCurrentBranch 展开当前节点
     *
     * @param treeTable org.jdesktop.swingx.JXTreeTable
     * @param root      cn.huhaoran.yaoyaolingxian.ui.CustomTreeTableImpl.GitBranchNode
     * @return void
     * @author huhaoran
     * @date 2024/8/12
     */
    public static void expandToCurrentBranch(JXTreeTable treeTable, GitBranchNode root) {
        try {
            GitBranchNode currentBranchNode = findCheckoutBranchNode(root);
            if (currentBranchNode == null) {
                currentBranchNode = getFirstBranch(treeTable, root);
            }
            if (currentBranchNode != null) {
                currentBranchNode.setSelected(true);
                TreePath path = new TreePath(currentBranchNode.getPath());
                treeTable.expandPath(path); // 展开到当前分支路径
                treeTable.scrollPathToVisible(path); // 滚动到当前分支路径
            }
        } catch (Exception e) {
            System.out.println("展开行失败"+e.getMessage());
        }
    }

    /**
     * 获取树中的第一个非目录节点
     *
     * @param treeTable the JXTreeTable to operate on
     * @param root      the root node to start from
     * @return the first non-directory node, or null if not found
     */
    public static GitBranchNode getFirstBranch(JXTreeTable treeTable, GitBranchNode root) {
        if (root == null || treeTable.getTreeTableModel().getChildCount(root) == 0) {
            return null;
        }
        int rootChildCount = treeTable.getTreeTableModel().getChildCount(root);
        if (rootChildCount == 0) {
            return null;
        }
        TreeTableModel treeTableModel = treeTable.getTreeTableModel();
        GitBranchNode child1 = (GitBranchNode) treeTableModel.getChild(root, 0);
        while (!child1.isLeaf()){
            child1 = (GitBranchNode) child1.getChildAt(0);
        }
        //child1.setSelected(true);
        // 遍历根节点的所有子节点
    /*    int childCount = treeTable.getTreeTableModel().getChildCount(root);
        for (int i = 0; i < childCount; i++) {
            Object child = treeTable.getTreeTableModel().getChild(root, i);
            if (child instanceof GitBranchNode) {
                GitBranchNode childNode = (GitBranchNode) child;
                if (childNode.getAllowsChildren() == false && childNode.isLeaf()) { // 判断是否是叶子节点（非目录节点）
                    return childNode;
                }
            }
        }*/
        return child1;
    }


    /**
     * findCurrentBranchNode 查找签出的分支
     *
     * @param node cn.huhaoran.yaoyaolingxian.ui.CustomTreeTableImpl.GitBranchNode
     * @return cn.huhaoran.yaoyaolingxian.ui.CustomTreeTableImpl.GitBranchNode
     * @author huhaoran
     * @date 2024/8/12
     */
    private static GitBranchNode findCheckoutBranchNode(GitBranchNode node) {
        if (node.isCheckedOut()) {
            return node;
        }
        for (int i = 0; i < node.getChildCount(); i++) {
            GitBranchNode child = (GitBranchNode) node.getChildAt(i);
            GitBranchNode result = findCheckoutBranchNode(child);
            if (result != null) {
                return result;
            }
        }
        return null;
    }

    /**
     * createTreeFromGitRepositories 通过项目创建节点树
     *
     * @param project com.intellij.openapi.project.Project
     * @return cn.huhaoran.yaoyaolingxian.ui.CustomTreeTableImpl.GitBranchNode
     * @author huhaoran
     * @date 2024/8/12
     */
    private static GitBranchNode createTreeFromGitRepositories(Project project) {
        GitRepositoryManager repositoryManager = GitRepositoryManager.getInstance(project);
        List<GitRepository> repositories = repositoryManager.getRepositories();

        GitBranchNode root = new GitBranchNode("Root", "", "", "", false, "","");

        // 添加“本地分支”和“远程分支”根节点
        GitBranchNode localBranchesNode = new GitBranchNode("本地分支", "本地分支", "", "", false, "","");
        GitBranchNode remoteBranchesNode = new GitBranchNode("远程分支", "远程分支", "", "", false, "","");


        for (GitRepository repo : repositories) {
            // 处理本地分支
            for (var localBranch : repo.getBranches().getLocalBranches()) {
                boolean isCheckedOut = repo.getCurrentBranch() != null && repo.getCurrentBranch().equals(localBranch);
                String fullBranchName = localBranch.getName();
                String[] branchParts = fullBranchName.split("/");
                addBranchToTree(localBranchesNode, branchParts, 0, fullBranchName, repo.getBranches().getHash(localBranch).asString(), "type1", isCheckedOut, getRemoteUrlForBranch(repo, localBranch.getName()));
            }

            // 处理远程分支
            for (var remoteBranch : repo.getBranches().getRemoteBranches()) {
                String fullBranchName = remoteBranch.getName();
                String[] branchParts = fullBranchName.split("/");
                addBranchToTree(remoteBranchesNode, branchParts, 0, fullBranchName, repo.getBranches().getHash(remoteBranch).asString(), "type2", false, remoteBranch.getRemote().getFirstUrl());
            }
        }
        if (localBranchesNode.getChildCount() > 0) {
            root.add(localBranchesNode);
        }
        if (remoteBranchesNode.getChildCount() > 0) {
            root.add(remoteBranchesNode);
        }
        return root;
    }

    /**
     * convertBranchesGitBranchNode 通过BranchNodeList分支列表创建节点树
     *
     * @param branches java.util.List<java.lang.String>
     * @return cn.huhaoran.yaoyaolingxian.ui.CustomTreeTableImpl.GitBranchNode
     * @author huhaoran
     * @date 2024/8/12
     */
    public static GitBranchNode convertBranchesGitBranchNode(List<String> branches) {
        GitBranchNode importRootNode = new GitBranchNode("Root", "", "", "", false, "","");

        GitBranchNode localBranchesNode = new GitBranchNode("本地分支", "", "", "", false, "","");
        GitBranchNode remoteBranchesNode = new GitBranchNode("远程分支", "", "", "", false, "","");

   /*     importRootNode.add(localBranchesNode);
        importRootNode.add(remoteBranchesNode);*/

        // 用于存储所有分支节点，key 是 hash 值，value 是 GitBranchNode
        Map<String, GitBranchNode> hashToNodeMap = new HashMap<>();

        for (String line : branches) {
            if (line.startsWith("Active code page")) {
                continue; // 忽略编码页信息
            }

            String[] parts = line.split(" ", 2);
            if (parts.length != 2) continue; // 确保分割后的数组有两个部分

            String hash = parts[0];
            String fullBranchName = parts[1];

            // 如果分支名是HEAD，标记对应的节点为签出状态
            if (fullBranchName.equals("HEAD")) {
                GitBranchNode checkoutNode = hashToNodeMap.get(hash);
                if (checkoutNode != null) {
                    checkoutNode.isCheckedOut = true;
                }
                continue; // 跳过处理 HEAD 节点
            }

            if (fullBranchName.startsWith("refs/heads/")) {
                String branchName = fullBranchName.substring("refs/heads/".length());
                GitBranchNode newNode = addBranchToTree(localBranchesNode, branchName, hash, fullBranchName, "local", "");
                hashToNodeMap.put(hash, newNode); // 存储节点与哈希值的映射
            } else if (fullBranchName.startsWith("refs/remotes/")) {
                String branchName = fullBranchName.substring("refs/remotes/".length());
                GitBranchNode newNode = addBranchToTree(remoteBranchesNode, branchName, hash, fullBranchName, "remote", "");
                hashToNodeMap.put(hash, newNode); // 存储节点与哈希值的映射
            }
        }

        if (localBranchesNode.getChildCount() > 0) {
            importRootNode.add(localBranchesNode);
        }
        if (remoteBranchesNode.getChildCount() > 0) {
            importRootNode.add(remoteBranchesNode);
        }

        return importRootNode;
    }

    private static GitBranchNode addBranchToTree(GitBranchNode parentNode, String branchName, String hash, String fullBranchName, String branchType, String originUrl) {
        String[] parts = branchName.split("/");

        GitBranchNode currentNode = parentNode;

        for (int i = 0; i < parts.length; i++) {
            boolean isLeaf = (i == parts.length - 1);

            GitBranchNode childNode = findChildNode(currentNode, parts[i]);

            if (childNode == null) {
                if (isLeaf) {
                    childNode = new GitBranchNode(parts[i], fullBranchName, hash, branchType, false, originUrl,processBranchName(fullBranchName));
                } else {
                    childNode = new GitBranchNode(parts[i], "", "", branchType, false, originUrl,"");
                }
                currentNode.add(childNode);
            }
            currentNode = childNode;
        }

        return currentNode;
    }


    private static void addBranchToTree(GitBranchNode parentNode, String[] branchParts, int index, String fullBranchName, String branchHash, String branchType, boolean isCheckedOut, String originUrl) {
        if (index >= branchParts.length) {
            return;
        }

        String part = branchParts[index];
        GitBranchNode childNode = null;

        // 检查当前父节点下是否已经有这个子节点
        for (int i = 0; i < parentNode.getChildCount(); i++) {
            GitBranchNode node = (GitBranchNode) parentNode.getChildAt(i);
            if (node.getBranchName().equals(part)) {
                childNode = node;
                break;
            }
        }

        // 如果没有找到现有子节点，创建一个新的
        if (childNode == null) {
            childNode = new GitBranchNode(part, fullBranchName, branchHash, branchType, isCheckedOut && index == branchParts.length - 1, originUrl,processBranchName((fullBranchName)));
            parentNode.add(childNode);

            // 对子节点按名称排序
            sortChildNodes(parentNode);
        }

        // 如果到了最后一个部分，设置详细信息
        if (index == branchParts.length - 1) {
            childNode.branchHash = branchHash;
            childNode.setSelected(isCheckedOut);
        }

        // 递归处理下一级
        addBranchToTree(childNode, branchParts, index + 1, fullBranchName, branchHash, branchType, isCheckedOut, originUrl);
    }
    /**
     * 处理分支名称，替换特定前缀并添加时间戳
     * @param originalName 原始的分支名称
     * @return 处理后的分支名称
     */
    public static String processBranchName(String originalName) {
        if(StringUtil.isNotEmpty(originalName)){
            // 获取当前日期并格式化为 yyMMdd
            String timestamp = new SimpleDateFormat("yyMMddHHmm").format(new Date());

            // 替换 refs/heads/ 和 refs/remotes/ 前缀
            if (originalName.startsWith("refs/heads/")) {
                return originalName.replace("refs/heads/", "导入/本地/" + timestamp+"/");
            } else if (originalName.startsWith("refs/remotes/")) {
                return originalName.replace("refs/remotes/", "导入/远程/"+ timestamp+"/") ;
            }
        }
        return originalName;
    }
    private static GitBranchNode findChildNode(GitBranchNode parentNode, String nodeName) {
        for (int i = 0; i < parentNode.getChildCount(); i++) {
            GitBranchNode childNode = (GitBranchNode) parentNode.getChildAt(i);
            if (childNode.getBranchName().equals(nodeName)) {
                return childNode;
            }
        }
        return null;
    }

    private static void sortChildNodes(GitBranchNode parentNode) {
        int childCount = parentNode.getChildCount();
        if (childCount > 1) {
            List<TreeNode> children = Collections.list(parentNode.children());
            children.sort((o1, o2) -> {
                GitBranchNode node1 = (GitBranchNode) o1;
                GitBranchNode node2 = (GitBranchNode) o2;

                boolean isNode1Directory = node1.getChildCount() > 0;
                boolean isNode2Directory = node2.getChildCount() > 0;

                // 目录节点始终排在最上方
                if (isNode1Directory && !isNode2Directory) {
                    return -1;
                } else if (!isNode1Directory && isNode2Directory) {
                    return 1;
                }

                // 字符串顺序颠倒
                return node2.getBranchName().compareTo(node1.getBranchName());
            });

            parentNode.removeAllChildren();
            for (TreeNode child : children) {
                parentNode.add((GitBranchNode) child);
            }
        }
    }

    private static String getRemoteUrlForBranch(GitRepository repo, String branchName) {
        return repo.getBranchTrackInfos().stream()
                .filter(info -> info.getLocalBranch().getName().equals(branchName))
                .findFirst()
                .map(info -> info.getRemote().getFirstUrl())
                .orElse(null);
    }


    /**
     * 获取所有被选中的 GitBranchNode 节点
     *
     * @param rootNode 根节点
     * @return 选中的 GitBranchNode 列表
     */
    public static List<GitBranchNode> getSelectedBranches(GitBranchNode rootNode) {
        List<GitBranchNode> selectedBranches = new ArrayList<>();
        // 如果当前节点被选中，加入到列表
        if (rootNode.isSelected()) {
            selectedBranches.add(rootNode);
        }
        // 递归遍历子节点并收集选中的节点
        for (int i = 0; i < rootNode.getChildCount(); i++) {
            GitBranchNode childNode = (GitBranchNode) rootNode.getChildAt(i);
            selectedBranches.addAll(getSelectedBranches(childNode));  // 递归调用
        }
        return selectedBranches;
    }

    /**
     * 递归遍历 GitBranchNode 树，查找选中的节点。
     *
     * @param node 当前 GitBranchNode
     * @param selectedBranches 用于存储选中的 GitBranchNode 节点的列表
     */
    private static void traverseGitBranchNodes(GitBranchNode node, List<GitBranchNode> selectedBranches) {
        // 检查当前节点是否被选中
        if (node.isSelected()) {
            selectedBranches.add(node);
        }
        // 递归遍历子节点
        for (int i = 0; i < node.getChildCount(); i++) {
            GitBranchNode childNode = (GitBranchNode) node.getChildAt(i);
            traverseGitBranchNodes(childNode, selectedBranches);
        }
    }

    /**
     * getFirstSelectedBranchName 获取第一个被选中的分支
     * @author huhaoran
     * @date 2024/9/10
     *
     * @param rootNode cn.huhaoran.yaoyaolingxian.ui.CustomTreeTableImpl.GitBranchNode
     * @return java.lang.String
     */
    private String getFirstSelectedBranchName(GitBranchNode rootNode) {
        for (int i = 0; i < rootNode.getChildCount(); i++) {
            GitBranchNode child = (GitBranchNode) rootNode.getChildAt(i);
            String branchName = findSelectedBranch(child);
            if (branchName != null) {
                return branchName;
            }
        }
        return null;
    }

    private String findSelectedBranch(GitBranchNode node) {
        if (node.isSelected()) {
            return node.getFullBranchName();
        }
        for (int i = 0; i < node.getChildCount(); i++) {
            GitBranchNode child = (GitBranchNode) node.getChildAt(i);
            String result = findSelectedBranch(child);
            if (result != null) {
                return result;
            }
        }
        return null;
    }
}
